package com.destin.basic.template;

import cn.hutool.core.io.IoUtil;
import com.destin.basic.constans.CommonConstants;
import com.destin.basic.eneity.Attachment;
import com.destin.basic.util.FileUtil;
import com.destin.basic.util.NameUtil;
import io.minio.MinioClient;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.util.StringUtils;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.InputStream;
import java.net.URLEncoder;
import java.text.SimpleDateFormat;
import java.util.*;

/**
 * 文件处理类
 *
 * @author destin
 * @since 2019-11-04
 */
@Data
@Slf4j(topic = "Minio对象存储模板begin...")
public class MinioTemplate implements FileTemplate {
    private static Logger logger = LoggerFactory.getLogger(MinioTemplate.class);

    private String bucketName;

    private String ossUrl;

    private MinioClient minioClient;

    private static final String DEFAULT_CHARSET = "UTF-8";

    public MinioTemplate(String bucketName, String ossUrl, MinioClient minioClient) {
        this.bucketName = bucketName;
        this.ossUrl = ossUrl;
        this.minioClient = minioClient;
    }

    /**
     * 上传主功能
     * @param file 文件对象
     * @return 返回
     */
    @Override
    public Map<String, String> uploadFile(MultipartFile file) throws Exception {
        Map<String, String> map = new HashMap<>(5);
        SimpleDateFormat sdf = new SimpleDateFormat("yyyyMM");
        String ymd = sdf.format(new Date());
        String objectName = ymd + "/" + UUID.randomUUID().toString() + NameUtil.getExtensionName(file.getOriginalFilename());
        String url;
        minioClient.putObject(bucketName, objectName, file.getInputStream(), file.getContentType());
        url = minioClient.getObjectUrl(bucketName, objectName);
        map.put("flag", "0");
        map.put("mess", "上传成功");
        map.put("url", url);
        map.put("urlval", url);
        map.put("path", bucketName + "/" + objectName);
        map.put("objectName", objectName);
        file.getInputStream().close();
        return map;
    }

    /**
     * 下载主功能
     * @param type 操作类型
     * @param attachment 附件对象
     * @param request HttpServletRequest
     * @param response HttpServletResponse
     * @throws Exception 异常
     */
    @Override
    public void download(String type, Attachment attachment, HttpServletRequest request, HttpServletResponse response) {
        String objName = splitFileName(attachment.getPath(), bucketName);
        String fileName = attachment.getName();
        try {
            InputStream inputStream = minioClient.getObject(bucketName, objName);
            String contentType = attachment.getSuffix();
            String userAgent = Optional.ofNullable(request.getHeader("User-Agent")).orElse("");
            //解决乱码
            if ( //IE 8 至 IE 10
                    userAgent.toUpperCase().contains("MSIE") ||
                            //IE 11 || Edge
                            userAgent.contains("Trident/7.0") || userAgent.contains("Edge")) {
                fileName = URLEncoder.encode(fileName, DEFAULT_CHARSET);
            } else {
                fileName = new String(fileName.getBytes(DEFAULT_CHARSET), "iso-8859-1");
            }
            if (CommonConstants.OPERATE_TYPE_DOWNLOAD.equalsIgnoreCase(type)) {
                response.setHeader("Content-Disposition", "attachment;filename=" + fileName);
                response.setContentType("application/force-download");
            } else {
                response.setContentType(contentType);
            }
            response.setHeader("Access-Control-Expose-headers", "Content-Disposition");
            response.setCharacterEncoding(DEFAULT_CHARSET);
            IoUtil.copy(inputStream, response.getOutputStream());
        } catch (Exception e) {
            log.error("Minio文件下载出现问题：{}"+ e.getMessage());
        }
    }

    /**
     * 删除文件
     * @param attachment 对象path
     */
    @Override
    public void removeObject(Attachment attachment) {
        String minioFilePath = splitFileName(attachment.getPath(), bucketName);
        try {
            minioClient.removeObject(bucketName, minioFilePath);
        } catch (Exception e) {
            log.error("file delete is error : {}", e.getMessage());
            // TODO 抛异常
//            throw BusinessException.create("附件删除异常！");
        }
    }

    /**
     * 通过文件路径获取文件在minio的真实路径，因为文件名称是随机的，解决文件名称相同上传覆盖问题
     * @param path 文件路径
     * @param bucketName 桶名称
     * @return 文件在minio的真实路径
     */
    private static String splitFileName(String path, String bucketName) {
        String[] pathArray = path.split(bucketName);
        if (pathArray.length == 0) {
            log.info("文件原始名称截取失败！");
            // TODO 抛异常
//            throw BusinessException.create("文件下载失败，请联系管理员！");
        }
        return pathArray[1];
    }
}
